/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package com.wxtech.heartbeat.client;

import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Random;

import org.apache.log4j.Logger;

import com.wxtech.heartbeat.util.Checksum;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * Handler implementation for the echo client.  It initiates the ping-pong
 * traffic between the echo client and server by sending the first message to
 * the server.
 */
public class HeartBeatClientHandler extends ChannelInboundHandlerAdapter {
	private static final Logger logger = Logger.getLogger(HeartBeatClientHandler.class);
	
//    private final ByteBuf firstMessage;
//    
//    private static final byte[] message = {
//    		0x68, 
//    		0x12, 0x23, 0x34, 0x45, 0x56, 0x67,
//    		0x68,
//    		0x01,
//    		0x04, 0x00,
//    		0x17, 0x05, 0x22, 0x15, 0x34, 0x55,
//    		0x11,
//    		0x01, 0x00,
//    		0x02, 0x00,
//    		0x00, 
//    		0x45, 0x46, 0x47, 0x48,
//    		0x00,
//    		0x16
//    };

    /**
     * Creates a client-side handler.
     */
    public HeartBeatClientHandler() {
    	/*
        firstMessage = Unpooled.buffer(EchoClient.SIZE);
        for (int i = 0; i < firstMessage.capacity(); i ++) {
            firstMessage.writeByte(0x68);
        }
        */
//    	firstMessage = Unpooled.buffer(32);
//    	firstMessage.setBytes(0, message);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {    	
    		//send hearbeat data to server
    		//一连上服务器就发送一个心跳信息，同时随意发一个信号
    		//最后就直接关闭连接
//        ctx.writeAndFlush(generateHeartBeatData());
//        ctx.writeAndFlush(generateBadCmdType());
        ctx.writeAndFlush(generateBadHB());
        logger.debug("channelActive()");
        ctx.close();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ctx.write(msg);
        logger.debug("channelRead()");
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
       ctx.flush();
       logger.debug("channelReadComplete()");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // Close the connection when an exception is raised.
        logger.error(cause);
        ctx.close();
    }
    
    private ByteBuf generateHeartBeatData() {
    		byte[] rawData = new byte[46];
    		rawData[0] = 0x02;//cmdtype heartbeat
    		rawData[1] = 0x01;//服务器端这个不检查， 所以随便给一个
    		rawData[2] = 0x00;
    		rawData[3] = 0x01;//biaohao
    		logger.debug("byte0-3 is good");
    		generateU64(rawData,4,8);
    		Calendar cal = Calendar.getInstance();
    		//直接拿到的年是比如2017的，转成byte时丢失数据，会导致服务器那边收到数据时年份出错
    		//所以就减掉1970
    		SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
    		String year = sdf.format(cal.getTime());
    		rawData[12] = (byte) (Integer.valueOf(year) - 2000);//year
    		rawData[13] = (byte) (cal.get(Calendar.MONTH) + 1) ;//month
    		rawData[14] = (byte) cal.get(Calendar.DATE);//day
    		rawData[15] = (byte) cal.get(Calendar.HOUR);//hour
    		rawData[16] = (byte) cal.get(Calendar.MINUTE);//minute
    		rawData[17] = (byte) cal.get(Calendar.SECOND);//second
    		logger.debug(cal.getTime() + ",year=" + rawData[12]);
    		logger.debug("byte until 17 is good");
    		generateBytes(rawData, 18, 20);//sim
    		generateU64(rawData,38,8);
    		//下面是算crc16  校验，用的算法类型必须和服务器一致
    		ByteBuffer bb = ByteBuffer.wrap(rawData);
    		int crc16 = Checksum.crc16(Checksum.CRC16_AUG_CCITT, bb);
    		logger.info("rawData=" + Arrays.toString(rawData));
    		logger.info("crc16=" + crc16);
    		//组装成48的 netty ByteBuf，就可以发送给服务器了
    		ByteBuf data = Unpooled.buffer(48);
    		data.writeBytes(rawData);
    		data.writeShort(crc16);
    		return data;
    }
    
    private ByteBuf generateBadCmdType() {
    		byte[] rawData = new byte[48];
    		generateBytes(rawData, 0, 48);
    		ByteBuf data = Unpooled.buffer(48);
    		data.writeBytes(rawData);
    		return data;
    }
    private ByteBuf generateBadHB() {
		byte[] rawData = new byte[48];
		generateBytes(rawData, 0, 48);
		rawData[0] = 0x02;
		rawData[1] = 0x01;
		rawData[2] = 0x00;
		rawData[3] = 0x01;
		ByteBuf data = Unpooled.buffer(48);
		data.writeBytes(rawData);
		return data;
    }
    
    private void generateBytes(byte[] rawData, int startIndex, int length) {
    		//generate n byte data
    		String a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ#=+)(*&";
    		Random r =  new Random();
    		for(int i=0; i<length;i++) {
    			int index = r.nextInt(a.length());
    			byte[] b = a.substring(index, index+1).getBytes();
    			rawData[startIndex + i] = b[b.length - 1];
    			logger.debug("s=" + a.substring(index, index+1)
    					+ ", b=" + b[b.length - 1]);
    			
    		}
    }

    private void generateU64(byte[] rawData, int startIndex, int length) {
		BigInteger bi = new BigInteger("170101000029");
		System.out.println(bi);
		Integer zero = new Integer(0);
		byte[] bytesBI = bi.toByteArray();
		byte[] bytes = {zero.byteValue(), zero.byteValue(), zero.byteValue(), bytesBI[0],bytesBI[1],bytesBI[2],bytesBI[3],bytesBI[4]};
		for(int i=0; i<length;i++) {
			rawData[startIndex + i] = bytes[i];
		}
}

    
}
